/**
 * axios封装
 * 请求拦截、响应拦截、错误统一处理
 */
import app from '@/main';
import axios from 'axios';
import $router from '@/router';
import { useCommonStore } from '@/store/main';

/** 
 * 跳转登录页
 * 携带当前页面路由，以期在登录页面完成登录后返回当前页面
 */
const toLogin = (errMsg: string): void => {
	const $store = useCommonStore();
	$store.setToken('')
	const fullPath: string = $router.currentRoute.value.fullPath
	const path: string = $router.currentRoute.value.path
	ElMessage({
		type: 'error',
		message: errMsg
	})
	if(fullPath && fullPath !== '/login') {
		const reg = /(.*redirect=)?(.+)$/
		const redirectPath = fullPath.match(reg)?.[2]
		$router.replace({
			path: '/login',        
			query: {
				redirect: redirectPath
			}
		});
	} else {
		if(path !== '/login') $router.replace({path: '/login'})
	}
}

/** 
 * 请求失败后的错误统一处理 
 * @params {Number} status 请求失败的状态码
 */
const errorHandle = (status: number|string, message: string): void => {
	app.config.globalProperties.$loading(false);
    // 状态码判断
    switch (status) {
		case 400: // 请求错误
			message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，客户端请求错误`);
			break;

        case 401: // 未登录状态，跳转登录页
			message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，未登录或未授权`);
            toLogin(message);
            break;
        
        case 403: // token过期
			message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，登录过期，请重新登录`);
			toLogin(message);
            break;
        
        case 404: // 请求不存在
			message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，请求的资源不存在`);
            break;

		case 500: // 服务器错误
			message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，服务器错误，请联系管理员`);
			break;

		case 'ERR_NETWORK':
			ElMessage.error(`错误代码: ${status}，网络不佳，请稍后重试`);
			break;

		case 'ERR_BAD_REQUEST':
			ElMessage.error(`错误代码: ${status}，请求错误，请检查网络或请求地址`);
			break;
			
        default:
            message ? ElMessage.error(`错误代码: ${status}，${message}`) : ElMessage.error(`错误代码: ${status}，请求错误`);
    }
};

// 创建axios实例
var instance = axios.create({
	// vite proxy 已经设置 target 代理地址，此处 baseURL 不用重复设置，或设置为空
	baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 1000 * 15
});
instance.defaults.headers.post['Content-Type'] = 'application/json';

let httpCount = 0;
/** 
 * 请求拦截器 
 * httpCount 累计请求次数，config.httpCount 本次请求属于第n次
 * 对应本次请求成功的 config.httpCount === res.config.httpCount
 * config.httpCount >= httpCount 成立时，最后一条请求已完成，此时可以取消loading事件
 * 用于判断本当前页面最后一次请求回调成功时，取消 loading 事件
 */ 
instance.interceptors.request.use(    
    config => {
		config.httpCount = ++httpCount;
        // 调用接口前启用loading方法
		app.config.globalProperties.$loading();
		const $store = useCommonStore();
        const token = $store.token;
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => Promise.reject(error)
);

/** 
 * 响应拦截器 
 */ 
instance.interceptors.response.use(    
    // 接口请求成功
    res => {
		if(!res || res.status !== 200) {
			errorHandle(res.status, res.data?.msg ?? res.data?.message);
            return Promise.reject(res);
		}
		let data = res.data;
		if(data?.code === 0) {
			// 最后一次请求完成后，次取消loading
			const _httpCount = res.config?.httpCount!
			_httpCount >= httpCount && app.config.globalProperties.$loading(false);
			
			if (data?.data?.length && data?.data[0].token && JSON.stringify(data.data) !== '{}') {
				const $store = useCommonStore();
				const result = data.data[0];
				$store.setToken(result.token);
			}
		} else {
			errorHandle('999', data.msg ?? '无数据，或 data 中没有 code');
		}
		return Promise.resolve(data);
    },    
    // 请求失败
    error => {
		errorHandle(error?.response?.status ?? error?.code, error?.response?.data?.msg ?? error?.message);
		return Promise.reject(error);
    }
);

export default instance;